home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include <stdio.h>
- #include <math.h>
-
- #include "vroom.h"
- #include "car.h"
- #include "ogl.h"
- #include "track.h"
- #include "collision.h"
- #include "sound.h"
-
- #define RF 0
- #define LF 1
- #define LR 2
- #define RR 3
-
-
- /* BEGIN PROTOTYPES -S collision.c */
- static void carsCollided( int i, int j ) ;
- static int checkLineWithLine( vec2 r0, vec2 r1, vec2 r2, vec2 r3 ) ;
- static int checkRectWithRect( vec2 a[4], vec2 b[4] ) ;
- static void mapCarCoords( int n, vec2 v[4] ) ;
- /* END PROTOTYPES -S collision.c */
-
-
- float collisionRadius2 ;
-
- extern int nTracks ;
- extern int nPlayers ;
- extern int debugOn ;
- extern int self ;
- extern int isRobot[] ;
- extern int updateStatWindow ;
- extern float carLength ;
- extern float carWidth ;
- extern Track *introTrack[] ;
- extern PlayerStruct player[] ;
- extern Car cars[MAX_PLAYERS] ;
- extern Sfx collideSfx ;
-
-
- /*------------------------------------------------------------------------------
- * Collision detection.
- *----------------------------------------------------------------------------*/
- void
- checkCollisions(
- void
- )
- {
- int i ;
- int j ;
- int iMapped ;
- int mapped[MAX_PLAYERS] ;
- float x ;
- float y ;
- float dx ;
- float dy ;
- float trackLen ;
- vec2 v[MAX_PLAYERS][4] ;
-
- mapped[0] = 0 ;
- mapped[1] = 0 ;
- mapped[2] = 0 ;
- mapped[3] = 0 ;
- mapped[4] = 0 ;
- mapped[5] = 0 ;
- mapped[6] = 0 ;
- mapped[7] = 0 ;
-
- trackLen = (float)nTracks ;
-
- for( i = 0 ; i < ( MAX_PLAYERS - 1 ) ; i++ )
- {
- if( !CAR_RACING( cars+i ) )
- {
- continue ;
- }
- x = cars[i].x ;
- y = cars[i].y ;
- for( j = i + 1 ; j < MAX_PLAYERS ; j++ )
- {
- if( !CAR_RACING( cars+j ) )
- {
- continue ;
- }
- dx = x - cars[j].x ;
- dy = y - cars[j].y ;
- if( dx * dx + dy * dy < collisionRadius2 )
- {
- if( !mapped[i] )
- {
- mapCarCoords( i, v[i] ) ;
- }
- if( !mapped[j] )
- {
- mapCarCoords( j, v[j] ) ;
- }
- if( checkRectWithRect( v[i], v[j] ) )
- {
- carsCollided( i, j ) ;
- }
- }
- }
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Map the corner points of a car.
- *----------------------------------------------------------------------------*/
- static void
- mapCarCoords(
- int n,
- vec2 v[4]
- )
- {
- float xc ;
- float yc ;
- float h ;
- float wc ;
- float ws ;
- float lc ;
- float ls ;
-
- xc = cars[n].x ;
- yc = cars[n].y ;
-
- h = cars[n].theta ;
-
- wc = 0.5f * cosf( h ) ;
- ws = 0.5f * sinf( h ) ;
-
- lc = carLength * wc ;
- ls = carLength * ws ;
-
- wc *= carWidth ;
- ws *= carWidth ;
-
- v[RF][0] = xc + wc - ls ;
- v[RF][1] = yc + ws + lc ;
-
- v[LF][0] = xc - wc - ls ;
- v[LF][1] = yc - ws + lc ;
-
- v[RR][0] = xc + wc + ls ;
- v[RR][1] = yc + ws - lc ;
-
- v[LR][0] = xc - wc + ls ;
- v[LR][1] = yc - ws - lc ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check if two rectangles overlap.
- *----------------------------------------------------------------------------*/
- static int
- checkRectWithRect(
- vec2 a[4],
- vec2 b[4]
- )
- {
- int a0 ;
- int a1 ;
- int b0 ;
- int b1 ;
-
- for( a0 = 0 ; a0 < 4 ; a0++ )
- {
- a1 = ( a0 + 1 ) % 4 ;
- for( b0 = 0 ; b0 < 4 ; b0++ )
- {
- b1 = ( b0 + 1 ) % 4 ;
- if( checkLineWithLine( a[a0], a[a1], b[b0], b[b1] ) )
- {
- return( 1 ) ;
- }
- }
- }
-
- return( 0 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Check for the intersection of two lines. One line is defined by the
- * points r0 and r1; the other line is defined by the points r2 and r3.
- *
- * Line 1 is defined by: Pt = r0 + s * ( r1 - r0 ) ; 0 <= s <= 1
- * Line 2 is defined by: Pt = r2 + t * ( r3 - r2 ) ; 0 <= t <= 1
- *
- * Set the two equal, solve for s and t. If s and t are both between
- * 0 and 1 (inclusive), the lines intersect. Return 1 if the lines
- * intersect, 0 otherwise.
- *----------------------------------------------------------------------------*/
- static int
- checkLineWithLine(
- vec2 r0,
- vec2 r1,
- vec2 r2,
- vec2 r3
- )
- {
- float denom ;
- float denom1 ;
- float denom2 ;
- float ns, nt ;
- float dx10 ;
- float dy10 ;
- float dx20 ;
- float dy20 ;
- float dx32 ;
- float dy32 ;
-
- dx10 = r1[0] - r0[0] ;
- dy10 = r1[1] - r0[1] ;
-
- dx20 = r2[0] - r0[0] ;
- dy20 = r2[1] - r0[1] ;
-
- dx32 = r3[0] - r2[0] ;
- dy32 = r3[1] - r2[1] ;
-
- denom1 = dy10 * dx32 ;
- denom2 = dx10 * dy32 ;
-
- /*
- * Fail if lines are parallel.
- */
- if( denom1 == denom2 )
- {
- return( 0 ) ;
- }
-
- denom = denom1 - denom2 ;
-
- ns = dx32 * dy20 - dy32 * dx20 ;
- nt = dx10 * dy20 - dy10 * dx20 ;
-
- /*
- * Fail if s or t are less than 0 (negative, which happens if ns or nt
- * are of different signs than denom) or greater than 1 (if abs(ns) or
- * abs(nt) are greater than abs(denom) ).
- */
- if( denom < 0 )
- {
- if( ns > 0 || nt > 0 || ns < denom || nt < denom )
- {
- return( 0 ) ;
- }
- }
- else
- {
- if( ns < 0 || nt < 0 || ns > denom || nt > denom )
- {
- return( 0 ) ;
- }
- }
- return( 1 ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Two cars collided.
- *----------------------------------------------------------------------------*/
- static void
- carsCollided(
- int i,
- int j
- )
- {
- int n ;
- int k ;
- vec2 a ;
- vec2 b ;
- float dx ;
- float dy ;
- float bs ;
- float theta ;
- float angle ;
- float s ;
- float len ;
-
- /*
- * First check if cars had vastly different headings. If so, this
- * probably means that they collided at a track crossing, so both
- * cars should wreck.
- */
- theta = player[i].headingDeg - player[j].headingDeg ;
- if( theta < -15.0f || theta > 15.0f )
- {
- a[0] = -cosf( cars[i].theta ) ;
- a[1] = -sinf( cars[i].theta ) ;
- wipeOutCar( &(cars[i]), a[0], a[1], ( theta > 0.0f ),
- WIPE_OUT_COLLISION );
- wipeOutCar( &(cars[j]), a[0], a[1], ( theta < 0.0f ),
- WIPE_OUT_COLLISION );
- theta = fmodf( theta + 720.0f, 360.0f ) - 180.0f ;
- if( ABSFUNC( theta ) < 90.0f )
- {
- if( isRobot[i] )
- {
- if( isRobot[j] && ( rand() % 2 ) == 1 )
- {
- cars[j].headOn = 1 ;
- }
- else
- {
- cars[i].headOn = 1 ;
- }
- }
- else if( isRobot[j] )
- {
- cars[j].headOn = 1 ;
- }
- }
- return ;
- }
- dx = cars[i].x - cars[j].x ;
- dy = cars[i].y - cars[j].y ;
- theta = atan2f( dy, dx ) ;
- angle = theta - 0.5f * ( cars[i].theta + cars[j].theta ) ;
- angle *= 180.0f / (float)M_PI ;
- angle = fmodf( angle + 720.0f, 360.0f ) ;
- k = -1 ;
- /*
- * Car i/j bumped by j/i from behind.
- */
- if( ( 85.0f <= angle && angle <= 95.0f ) ||
- ( 265.0f <= angle && angle <= 275.0f ) )
- {
- s = cars[i].speed ;
- cars[i].speed = cars[j].speed ;
- cars[j].speed = s ;
-
- s = 1.1f * carLength - sqrtf( dx * dx + dy * dy ) ;
- n = ( angle < 180.0f ) ? i : j ;
- if( cars[n].speed > 0.0f )
- {
- cars[n].track->follow( cars[n].track,
- &(cars[n]), s / cars[n].speed ) ;
- }
- else
- {
- cars[n].speed = 0.1f * TOP_SPEED ;
- cars[n].track->follow( cars[n].track,
- &(cars[n]), s / cars[n].speed ) ;
- cars[n].speed = 0.0f ;
- }
- updatePlayerView( n ) ;
- n = ( i ^ j ) ^ n ;
- cars[n].speed *= 0.75f ;
- }
- /*
- * Car i side swiped from left/right rear by j.
- */
- else if( angle < 180.0f )
- {
- s = 0.5f * ( cars[i].speed + cars[j].speed ) ;
- n = randomChoice( s / TOP_SPEED ) ;
- if( n )
- {
- angle = 90.0f - angle ;
- if( randomChoice( ABSFUNC( angle ) / 180.0f ) )
- {
- k = j ;
- }
- else
- {
- k = i ;
- }
- }
- else
- {
- cars[i].status &= ~(CHANGE_LANE_RIGHT |
- CHANGE_LANE_LEFT) ;
- cars[j].status &= ~(CHANGE_LANE_RIGHT |
- CHANGE_LANE_LEFT) ;
- if( angle < 90.0f )
- {
- cars[i].status |= CHANGE_LANE_RIGHT ;
- cars[j].status |= CHANGE_LANE_LEFT ;
- }
- else
- {
- cars[i].status |= CHANGE_LANE_LEFT ;
- cars[j].status |= CHANGE_LANE_RIGHT ;
- }
- }
- }
- /*
- * Car j side swiped from left/right rear by i.
- */
- else
- {
- s = 0.5f * ( cars[i].speed + cars[j].speed ) ;
- n = randomChoice( s / TOP_SPEED ) ;
- if( n )
- {
- angle = 270.0f - angle ;
- if( randomChoice( ABSFUNC( angle ) / 180.0f ) )
- {
- k = i ;
- }
- else
- {
- k = j ;
- }
- }
- else
- {
- cars[i].status &= ~(CHANGE_LANE_RIGHT |
- CHANGE_LANE_LEFT) ;
- cars[j].status &= ~(CHANGE_LANE_RIGHT |
- CHANGE_LANE_LEFT) ;
- if( angle > 270.0f )
- {
- cars[i].status |= CHANGE_LANE_RIGHT ;
- cars[j].status |= CHANGE_LANE_LEFT ;
- }
- else
- {
- cars[i].status |= CHANGE_LANE_LEFT ;
- cars[j].status |= CHANGE_LANE_RIGHT ;
- }
- }
- }
-
- if( k == i )
- {
- a[0] = cosf( theta ) ;
- a[1] = sinf( theta ) ;
- cars[i].x += a[0] * carLength ;
- cars[i].y += a[1] * carLength ;
- wipeOutCar( &(cars[i]), a[0], a[1], ( angle < 90.0f ),
- WIPE_OUT_COLLISION );
- if( j == self )
- {
- sfxPlay( collideSfx ) ;
- }
- cars[j].status |= CAR_BUMP ;
- if( cars[j].status & ( CHANGE_LANE_LEFT |
- CHANGE_LANE_RIGHT ) != 0 )
- {
- cars[j].status ^= CHANGE_LANE_LEFT |
- CHANGE_LANE_RIGHT ;
- }
- }
- else if( k == j )
- {
- a[0] = -cosf( theta ) ;
- a[1] = -sinf( theta ) ;
- wipeOutCar( &(cars[j]), a[0], a[1], ( angle > 270.0f ),
- WIPE_OUT_COLLISION ) ;
- if( i == self )
- {
- sfxPlay( collideSfx ) ;
- }
- cars[i].status |= CAR_BUMP ;
- if( cars[i].status & ( CHANGE_LANE_LEFT |
- CHANGE_LANE_RIGHT ) != 0 )
- {
- cars[i].status ^= CHANGE_LANE_LEFT |
- CHANGE_LANE_RIGHT ;
- }
- }
- else
- {
- cars[i].status |= CAR_BUMP ;
- cars[j].status |= CAR_BUMP ;
- if( i == self || j == self )
- {
- sfxPlay( collideSfx ) ;
- }
- }
- }
-
-
-
-